// 数据存储模块
// 提供期权数据的存储和查询功能

use crate::db::config::DbConfig;
use crate::types::*;
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use surrealdb::engine::local::{Db, RocksDb};
use surrealdb::Surreal;
use std::sync::Arc;

/// 期权数据存储
/// 
/// 使用 SurrealDB 嵌入式数据库存储和查询期权数据
#[derive(Clone)]
pub struct OptionStore {
    db: Arc<Surreal<Db>>,
    config: DbConfig,
}

impl OptionStore {
    /// 创建新的数据存储实例
    /// 
    /// # 参数
    /// 
    /// * `config` - 数据库配置
    /// 
    /// # 示例
    /// 
    /// ```rust,no_run
    /// use akoption::db::{OptionStore, DbConfig};
    /// 
    /// #[tokio::main]
    /// async fn main() -> anyhow::Result<()> {
    ///     let config = DbConfig::default();
    ///     let store = OptionStore::new(config).await?;
    ///     Ok(())
    /// }
    /// ```
    pub async fn new(config: DbConfig) -> Result<Self> {
        // 确保数据目录存在
        if let Some(parent) = config.path.parent() {
            tokio::fs::create_dir_all(parent)
                .await
                .context("创建数据目录失败")?;
        }
        
        // 连接到 RocksDB
        let db = Surreal::new::<RocksDb>(config.path.to_string_lossy().to_string())
            .await
            .context("连接数据库失败")?;
        
        // 使用命名空间和数据库
        db.use_ns(&config.namespace)
            .use_db(&config.database)
            .await
            .context("设置命名空间和数据库失败")?;
        
        Ok(Self {
            db: Arc::new(db),
            config,
        })
    }
    
    /// 使用默认配置创建存储实例
    /// 
    /// # 示例
    /// 
    /// ```rust,no_run
    /// use akoption::db::OptionStore;
    /// 
    /// #[tokio::main]
    /// async fn main() -> anyhow::Result<()> {
    ///     let store = OptionStore::with_default_config().await?;
    ///     Ok(())
    /// }
    /// ```
    pub async fn with_default_config() -> Result<Self> {
        Self::new(DbConfig::default()).await
    }
    
    // ============ 东方财富数据存储 ============
    
    /// 存储东方财富期权快照数据
    /// 
    /// # 参数
    /// 
    /// * `data` - 期权快照数据列表
    /// 
    /// # 示例
    /// 
    /// ```rust,no_run
    /// use akoption::{option_current_em, db::OptionStore};
    /// 
    /// #[tokio::main]
    /// async fn main() -> anyhow::Result<()> {
    ///     let store = OptionStore::with_default_config().await?;
    ///     let data = option_current_em().await?;
    ///     store.save_em_options(&data).await?;
    ///     Ok(())
    /// }
    /// ```
    pub async fn save_em_options(&self, data: &[EmOptionTick]) -> Result<()> {
        for item in data {
            let _: Option<EmOptionTick> = self.db
                .create(("em_options", &item.code))
                .content(item.clone())
                .await
                .context("保存东方财富期权数据失败")?;
        }
        Ok(())
    }
    
    /// 查询东方财富期权数据
    /// 
    /// # 参数
    /// 
    /// * `code` - 期权代码（可选，为 None 时返回所有数据）
    /// 
    /// # 示例
    /// 
    /// ```rust,no_run
    /// use akoption::db::OptionStore;
    /// 
    /// #[tokio::main]
    /// async fn main() -> anyhow::Result<()> {
    ///     let store = OptionStore::with_default_config().await?;
    ///     
    ///     // 查询所有数据
    ///     let all_data = store.query_em_options(None).await?;
    ///     
    ///     // 查询特定期权
    ///     let specific = store.query_em_options(Some("10004355")).await?;
    ///     
    ///     Ok(())
    /// }
    /// ```
    pub async fn query_em_options(&self, code: Option<&str>) -> Result<Vec<EmOptionTick>> {
        if let Some(code) = code {
            let result: Option<EmOptionTick> = self.db
                .select(("em_options", code))
                .await
                .context("查询东方财富期权数据失败")?;
            Ok(result.into_iter().collect())
        } else {
            let results: Vec<EmOptionTick> = self.db
                .select("em_options")
                .await
                .context("查询东方财富期权数据失败")?;
            Ok(results)
        }
    }
    
    /// 存储期权价值分析数据
    /// 
    /// # 参数
    /// 
    /// * `data` - 价值分析数据列表
    pub async fn save_value_analysis(&self, data: &[EmValueAnalysis]) -> Result<()> {
        for item in data {
            let _: Option<EmValueAnalysis> = self.db
                .create(("value_analysis", &item.code))
                .content(item.clone())
                .await
                .context("保存价值分析数据失败")?;
        }
        Ok(())
    }
    
    /// 查询期权价值分析数据
    pub async fn query_value_analysis(&self, code: Option<&str>) -> Result<Vec<EmValueAnalysis>> {
        if let Some(code) = code {
            let result: Option<EmValueAnalysis> = self.db
                .select(("value_analysis", code))
                .await
                .context("查询价值分析数据失败")?;
            Ok(result.into_iter().collect())
        } else {
            let results: Vec<EmValueAnalysis> = self.db
                .select("value_analysis")
                .await
                .context("查询价值分析数据失败")?;
            Ok(results)
        }
    }
    
    /// 存储期权风险分析数据（Greeks）
    /// 
    /// # 参数
    /// 
    /// * `data` - 风险分析数据列表
    pub async fn save_risk_analysis(&self, data: &[EmRiskAnalysis]) -> Result<()> {
        for item in data {
            let _: Option<EmRiskAnalysis> = self.db
                .create(("risk_analysis", &item.code))
                .content(item.clone())
                .await
                .context("保存风险分析数据失败")?;
        }
        Ok(())
    }
    
    /// 查询期权风险分析数据
    pub async fn query_risk_analysis(&self, code: Option<&str>) -> Result<Vec<EmRiskAnalysis>> {
        if let Some(code) = code {
            let result: Option<EmRiskAnalysis> = self.db
                .select(("risk_analysis", code))
                .await
                .context("查询风险分析数据失败")?;
            Ok(result.into_iter().collect())
        } else {
            let results: Vec<EmRiskAnalysis> = self.db
                .select("risk_analysis")
                .await
                .context("查询风险分析数据失败")?;
            Ok(results)
        }
    }
    
    // ============ 新浪财经数据存储 ============
    
    /// 存储上交所期权合约列表
    /// 
    /// # 参数
    /// 
    /// * `data` - 合约列表数据
    pub async fn save_sse_contracts(&self, data: &[SseContract]) -> Result<()> {
        for item in data {
            // 使用update替换旧数据，如果不存在则创建
            let _: Option<SseContract> = self.db
                .update(("sse_contracts", &item.contract_code))
                .content(item.clone())
                .await
                .context("保存合约数据失败")?;
        }
        Ok(())
    }
    
    /// 查询上交所期权合约
    pub async fn query_sse_contracts(&self, code: Option<&str>) -> Result<Vec<SseContract>> {
        if let Some(code) = code {
            let result: Option<SseContract> = self.db
                .select(("sse_contracts", code))
                .await
                .context("查询合约数据失败")?;
            Ok(result.into_iter().collect())
        } else {
            let results: Vec<SseContract> = self.db
                .select("sse_contracts")
                .await
                .context("查询合约数据失败")?;
            Ok(results)
        }
    }
    
    /// 存储期权到期日列表
    /// 
    /// # 参数
    /// 
    /// * `data` - 到期日列表
    pub async fn save_expire_dates(&self, data: &[String]) -> Result<()> {
        use chrono::Utc;
        let timestamp = Utc::now().timestamp();
        
        // 先删除旧数据
        let _: Vec<serde_json::Value> = self.db
            .query("DELETE FROM sse_expire_dates")
            .await
            .context("删除旧的到期日数据失败")?
            .take(0)?;
        
        for (idx, date) in data.iter().enumerate() {
            #[derive(Serialize, Deserialize)]
            struct ExpireDate {
                date: String,
                timestamp: i64,
            }
            
            let record = ExpireDate {
                date: date.clone(),
                timestamp,
            };
            
            let _: Option<ExpireDate> = self.db
                .create(("sse_expire_dates", format!("{}_{}", timestamp, idx)))
                .content(record)
                .await
                .context("保存到期日数据失败")?;
        }
        Ok(())
    }
    
    /// 存储期权合约代码列表
    /// 
    /// # 参数
    /// 
    /// * `expire_date` - 到期日
    /// * `data` - 合约代码列表
    pub async fn save_option_codes(&self, expire_date: &str, data: &[String]) -> Result<()> {
        for code in data {
            #[derive(Serialize, Deserialize)]
            struct OptionCode {
                code: String,
                expire_date: String,
            }
            
            let record = OptionCode {
                code: code.clone(),
                expire_date: expire_date.to_string(),
            };
            
            // 使用update替换旧数据，如果不存在则创建
            let _: Option<OptionCode> = self.db
                .update(("sse_option_codes", code))
                .content(record)
                .await
                .context("保存期权代码失败")?;
        }
        Ok(())
    }
    
    /// 存储期权龙虎榜数据
    /// 
    /// # 参数
    /// 
    /// * `data` - 龙虎榜数据（通用JSON格式）
    pub async fn save_option_lhb(&self, data: &[serde_json::Value]) -> Result<()> {
        use chrono::Utc;
        let timestamp = Utc::now().timestamp();
        
        // 先删除旧数据
        let _: Vec<serde_json::Value> = self.db
            .query("DELETE FROM option_lhb")
            .await
            .context("删除旧的龙虎榜数据失败")?
            .take(0)?;
        
        for (idx, item) in data.iter().enumerate() {
            // 将 JSON 数据转换为字符串，然后使用 query 插入
            let json_str = serde_json::to_string(item)
                .context("序列化JSON数据失败")?;
            
            let record_id = format!("{}_{}", timestamp, idx);
            let query = format!("CREATE option_lhb:⟨{}⟩ CONTENT {}", record_id, json_str);
            
            let _: Vec<serde_json::Value> = self.db
                .query(query)
                .await
                .context("保存龙虎榜数据失败")?
                .take(0)?;
        }
        Ok(())
    }
    
    /// 存储期权折溢价数据
    /// 
    /// # 参数
    /// 
    /// * `data` - 折溢价数据（通用JSON格式）
    pub async fn save_premium_analysis(&self, data: &[serde_json::Value]) -> Result<()> {
        for item in data {
            if let Some(code) = item.get("代码").and_then(|v| v.as_str()) {
                // 将 JSON 数据转换为字符串，然后使用 query 插入
                let json_str = serde_json::to_string(item)
                    .context("序列化JSON数据失败")?;
                
                // 使用update替换旧数据，如果不存在则创建
                let query = format!("UPDATE premium_analysis:⟨{}⟩ CONTENT {}", code, json_str);
                
                let _: Vec<serde_json::Value> = self.db
                    .query(query)
                    .await
                    .context("保存折溢价数据失败")?
                    .take(0)?;
            }
        }
        Ok(())
    }
    
    /// 存储期权分钟行情数据
    /// 
    /// # 参数
    /// 
    /// * `symbol` - 合约代码
    /// * `data` - 分钟行情数据（通用JSON格式）
    pub async fn save_minute_data(&self, symbol: &str, data: &[serde_json::Value]) -> Result<()> {
        // 直接使用update替换数据，如果不存在则创建
        let table = "minute_data";
        for (idx, item) in data.iter().enumerate() {
            // 将 JSON 数据转换为字符串，然后使用 query 插入
            let json_str = serde_json::to_string(item)
                .context("序列化JSON数据失败")?;
            
            // 使用 r 前缀创建原始字符串记录ID，避免中文字符问题
            let record_id = format!("{}_{}", symbol, idx);
            let query = format!("UPDATE {}:⟨{}⟩ CONTENT {}", table, record_id, json_str);
            
            let _: Vec<serde_json::Value> = self.db
                .query(query)
                .await
                .context("保存分钟行情数据失败")?
                .take(0)?;
        }
        Ok(())
    }
    
    /// 存储期权日线行情数据
    /// 
    /// # 参数
    /// 
    /// * `symbol` - 合约代码
    /// * `data` - 日线行情数据（通用JSON格式）
    pub async fn save_daily_data(&self, symbol: &str, data: &[serde_json::Value]) -> Result<()> {
        // 直接使用update替换数据，如果不存在则创建
        let table = "daily_data";
        for (idx, item) in data.iter().enumerate() {
            // 将 JSON 数据转换为字符串，然后使用 query 插入
            let json_str = serde_json::to_string(item)
                .context("序列化JSON数据失败")?;
            
            let record_id = format!("{}_{}", symbol, idx);
            let query = format!("UPDATE {}:⟨{}⟩ CONTENT {}", table, record_id, json_str);
            
            let _: Vec<serde_json::Value> = self.db
                .query(query)
                .await
                .context("保存日线行情数据失败")?
                .take(0)?;
        }
        Ok(())
    }
    
    // ============ 通用查询方法 ============
    
    /// 执行自定义 SurrealQL 查询
    /// 
    /// # 参数
    /// 
    /// * `query` - SurrealQL 查询语句
    /// 
    /// # 示例
    /// 
    /// ```rust,no_run
    /// use akoption::db::OptionStore;
    /// 
    /// #[tokio::main]
    /// async fn main() -> anyhow::Result<()> {
    ///     let store = OptionStore::with_default_config().await?;
    ///     
    ///     // 查询最新价大于 1.0 的期权
    ///     let query = "SELECT * FROM em_options WHERE last > 1.0";
    ///     let results: Vec<serde_json::Value> = store.query(query).await?;
    ///     
    ///     Ok(())
    /// }
    /// ```
    pub async fn query<T>(&self, query: &str) -> Result<Vec<T>>
    where
        T: for<'de> Deserialize<'de>,
    {
        let mut result = self.db
            .query(query)
            .await
            .context("执行查询失败")?;
        
        let data: Vec<T> = result
            .take(0)
            .context("获取查询结果失败")?;
        
        Ok(data)
    }
    
    /// 删除指定表的所有数据
    /// 
    /// # 参数
    /// 
    /// * `table` - 表名
    /// 
    /// # 示例
    /// 
    /// ```rust,no_run
    /// use akoption::db::OptionStore;
    /// 
    /// #[tokio::main]
    /// async fn main() -> anyhow::Result<()> {
    ///     let store = OptionStore::with_default_config().await?;
    ///     store.clear_table("em_options").await?;
    ///     Ok(())
    /// }
    /// ```
    pub async fn clear_table(&self, table: &str) -> Result<()> {
        let query = format!("DELETE FROM {}", table);
        self.db
            .query(&query)
            .await
            .context("清空表失败")?;
        Ok(())
    }
    
    /// 获取表中的记录数
    /// 
    /// # 参数
    /// 
    /// * `table` - 表名
    /// 
    /// # 示例
    /// 
    /// ```rust,no_run
    /// use akoption::db::OptionStore;
    /// 
    /// #[tokio::main]
    /// async fn main() -> anyhow::Result<()> {
    ///     let store = OptionStore::with_default_config().await?;
    ///     let count = store.count_records("em_options").await?;
    ///     println!("记录数: {}", count);
    ///     Ok(())
    /// }
    /// ```
    pub async fn count_records(&self, table: &str) -> Result<usize> {
        #[derive(Deserialize)]
        struct CountResult {
            count: usize,
        }
        
        let query = format!("SELECT count() as count FROM {} GROUP ALL", table);
        let mut result = self.db
            .query(&query)
            .await
            .context("查询记录数失败")?;
        
        let counts: Vec<CountResult> = result
            .take(0)
            .context("获取记录数失败")?;
        
        Ok(counts.first().map(|c| c.count).unwrap_or(0))
    }
    
    /// 获取数据库配置
    pub fn config(&self) -> &DbConfig {
        &self.config
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::path::PathBuf;
    
    #[tokio::test]
    async fn test_store_creation() {
        let config = DbConfig::new(
            PathBuf::from("/tmp/test_akoption.db"),
            "test",
            "options"
        );
        
        let store = OptionStore::new(config).await;
        assert!(store.is_ok());
    }
}
